<template>
  <div>
    <div class="btn">
      <button @click="beginFun">填充</button>
      <button @click="clearFun">清空</button>
    </div>
    <div class="box">
      <div class="line" v-for="(ary, i) in arr" :key="i">
        <div
          class="item"
          :key="index"
          v-for="(item, index) in ary"
          :class="(i == 2 || i == 5) ? 'border-bottom-line' : ''"
          :style="(index == 2 || index == 5) ? 'border-right: 2px solid red' : ''"
        >
          <input v-if="isAdd" type="text" v-model="arr[i][index]">
          <div v-else :class="arr[i][index] ? '' : 'red'">{{ endAry[i][index] || '-' }}</div>
        </div>
      </div>
    </div>
  </div>
</template>
<script>
export default {
  data() {
    return {
      arr: [
        [9, null, null, 5, 2, 1, 4, 6, null],
        [null, 4, 2, 7, 8, null, null, 1, null],
        [5, null, null, 4, 6, null, 7, null, 8],
        [8, null, 9, 3, null, null, 1, 5, 6],
        [null, 1, 5, null, null, 8, 2, null, 7],
        [3, null, null, null, null, null, 8, null, 4],
        [null, 5, 6, null, 1, 7, 3, null, null],
        [null, 9, null, null, null, 6, 5, null, 1],
        [null, null, 3, null, null, null, null, null, null]
      ],
      endAry: null,
      isAdd: true,
      nums: [1, 2, 3, 4, 5, 6, 7, 8, 9],
      kMap: {
        0: [0, 1, 2],
        1: [0, 1, 2],
        2: [0, 1, 2],
        3: [3, 4, 5],
        4: [3, 4, 5],
        5: [3, 4, 5],
        6: [6, 7, 8],
        7: [6, 7, 8],
        8: [6, 7, 8],
      }
    }
  },
  created() {
    this.clearFun()
  },
  methods: {
    clearFun() {
      this.isAdd = true;
      let arr = []
      for (let i = 0; i < 9; i++) {
        arr.push(new Array(9))
      }
      this.arr = arr;
      this.endAry = arr;
    },
    beginFun() {
      this.isAdd = false;
      let ary = JSON.parse(JSON.stringify(this.arr));
      this.endAry = ary;
      this.setAry(ary, 0, 0, 0);
    },
    setAry(ary, i1, i2) {
      if (!this.isTrueNum(ary, i1, i2)) {
        ary[i1][i2] = null;
        return false;
      }
      if (ary[i1][i2]) {
        i2++;
        if (i2 == 9) {
          i1++;
          i2 = 0;
          if (i1 == 9) {
            return ary;
          }
        }
      }
      for (let i = i1; i < ary.length; i++) {
        let ary1 = ary[i];
        for (let j = i2; j < ary1.length; j++) {
          if (!ary1[j]) {
            let index = 0;
            for (index = 0; index < this.nums.length; index++) {
              ary1[j] = this.nums[index];
              if (this.setAry(ary, i, j)) {
                break
              }
            }
            if (index == 9) {
              ary1[j] = null;
              return false
            }
          }
        }
        i2 = 0;
      }
      return ary;
    },
    isTrueNum(ary, i, j) {
      if (!ary[i][j]) {
        return true;
      }
      if (!this.isH(ary, i, j)) {
        return false;
      }
      if (!this.isS(ary, i, j)) {
        return false;
      }
      if (!this.isK(ary, i, j)) {
        return false;
      }
      return true;
    },
    isH(ary, i, j) {
      let arr = ary[i];
      for (let k = 0; k < arr.length; k++) {
        if (k != j) {
          if (arr[j] == arr[k]) {
            return false
          }
        }
      }
      return true
    },
    isS(ary, i, j) {
      for (let k = 0; k < ary.length; k++) {
        if (k != i) {
          if (ary[k][j] == ary[i][j]) {
            return false;
          }
        }
      }
      return true
    },
    isK(ary, i, j) {
      let iary = this.kMap[i];
      let jary = this.kMap[j];
      for (let i1 = 0; i1 < iary.length; i1++) {
        for (let j1 = 0; j1 < jary.length; j1++) {
          let v1 = iary[i1];
          let v2 = jary[j1]
          if (i != v1 && j != v2) {
            if (ary[i][j] == ary[v1][v2]) {
              return false;
            }
          }
        }
      }
      return true
    }
  }
}
</script>
<style scoped>
.btn > button {
  padding: 4px 10px;
  margin-right: 20px;
}

.btn {
  padding-bottom: 20px;
}

.box {
  width: 450px;
  height: 450px;
  border: 1px solid #cccccc;
  display: flex;
  align-items: center;
  flex-direction: column;
}

.box > div {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
}

.box > div > div {
  flex: 1;
  height: 100%;
  border: 1px solid #cccccc;
  text-align: center;
}

.box > div > div > div {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
}

input {
  width: 100%;
  height: 100%;
  border: 0;
  padding: 0;
  outline: none;
  text-align: center;
  font-size: 20px;
}

.box > div > .border-bottom-line {
  border-bottom: 2px solid red;
}

.red {
  color: red;
  font-size: 20px;
}
</style>
